`timescale 1ns / 1ps
`default_nettype none
`include "InstrHeader.h"
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2019/07/02 10:32:41
// Design Name: 
// Module Name: DecodeState
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module DecodeState(
    input	wire	Clk,
    input	wire	Clr,
    input	wire	W_WriteRegEnable,
    input   wire	[4:0]   W_RegWriteId,
    input   wire	[31:0]  W_RegWriteData,

	input	wire	[31:0]	I_PC_Pass,
    input   wire	[31:0]  I_PC,
    input   wire	[31:0]  I_MipsInstr,
	input	wire	[31:0]	W_PC,
    output  wire	[31:0]  D_NewPC_Pass,///pass through  
	output	reg	[31:0]	D_PC,
	output	reg	[31:0]	D_Instr,
	output	reg [4:0]	D_RsID,
	output	reg [4:0]	D_RtID,
	output  reg [31:0]  D_RsData,
    output  reg [31:0]  D_RtData,
    output  reg [4:0]   D_Shamt,
    output  reg [15:0]  D_Imm16,
    output	reg [`InstrBusWidth]	D_InstrBus,
    
    input   wire	[3:0]   E_T,
    input   wire	E_WriteRegEnable,
    input   wire	[4:0]   E_RegId,
    input   wire	[31:0]  E_Data,
	input	wire	E_XALU_Busy,
	
    output  reg [3:0]   D_T,
    output  reg         D_WriteRegEnable,
    output  reg [4:0]   D_RegId,

    output 	wire	D_stall_Pass,

	input	wire	I_sram_busy
    );
	
    wire [25:0]     Imm26_Inter;
    wire [15:0]     Imm16_Inter;
    wire [4:0]		Rs_Inter,Rt_Inter,Rd_Inter,Shamt_Inter;
    wire [`InstrBusWidth]		InstrBus_Inter;
	wire			WriteRegEnable_Inter;
	wire [4:0] 		WriteRegId_Inter;
	
    DecodeUnit  DecodeUnit(.MipsInstr(I_MipsInstr),.Rs(Rs_Inter),.Rt(Rt_Inter),.Rd(Rd_Inter),.Shamt(Shamt_Inter),.Imm16(Imm16_Inter),.Imm26(Imm26_Inter),
							.RegWriteEnable(WriteRegEnable_Inter),.WriteRegId(WriteRegId_Inter),.InstrBus(InstrBus_Inter));

    wire [31:0] RsData_Inter,RtData_Inter;
    GRF GRF(.Clk(Clk),.Clr(Clr),.PC(W_PC),.Addr1(Rs_Inter),.Addr2(Rt_Inter),
            .WriteAddr(W_RegWriteId),.WriteEnable(W_WriteRegEnable),.WriteData(W_RegWriteData),
            .OutData1(RsData_Inter),.OutData2(RtData_Inter));

    /////////////////////转发//// 
	wire    [31:0]  MF_Rs = (Rs_Inter!=0 && Rs_Inter==E_RegId && E_T==0 && E_WriteRegEnable)    ?   E_Data:
                                                                                                    RsData_Inter;
    wire    [31:0]  MF_Rt = (Rt_Inter!=0 && Rt_Inter==E_RegId && E_T==0 && E_WriteRegEnable)    ?   E_Data:
                                                                                                    RtData_Inter;
    //////////////////////
    NPC NPC(.MipsInstr(I_MipsInstr),.RsData(MF_Rs),.RtData(MF_Rt),.PC(I_PC_Pass),.NewPC(D_NewPC_Pass),.Clr(Clr));
	wire `InstrBusWireSet;
	assign {`InstrBusWireSet} = InstrBus_Inter;
	wire MultCalFamily_Inter = (mult|multu|div|divu);
	reg	D_MultCalFamily;
    wire    [3:0]   T_Inter;
    StallCtrlUnit StallCtrlUnit(.InstrBus(InstrBus_Inter),.Rs(Rs_Inter),.Rt(Rt_Inter),.D_T(D_T),.D_WriteRegEnable(D_WriteRegEnable),.D_RegId(D_RegId),.E_T(E_T),.E_WriteRegEnable(E_WriteRegEnable),.E_RegId(E_RegId),
                                .stall(D_stall_Pass),.T(T_Inter),.XALU_Busy(E_XALU_Busy),.D_MultCalFamily(D_MultCalFamily));
	
    initial begin
			D_PC <= 0;
			D_RsID <= 0;
			D_RtID <= 0;
			D_RsData <= 0;
			D_RtData <= 0;
			D_Shamt <= 0;
			D_Imm16 <= 0;
			D_InstrBus <= 0;
			D_T <= 0;
			D_WriteRegEnable <= 0;
			D_RegId <= 0;
			D_MultCalFamily <= 0;
	end
    always @ (posedge Clk)  begin
        if(Clr|D_stall_Pass|I_sram_busy) begin
			D_PC <= 0;
			D_Instr<=0;
			D_RsID <= 0;
			D_RtID <= 0;
			D_RsData <= 0;
			D_RtData <= 0;
			D_Shamt <= 0;
			D_Imm16 <= 0;
			D_InstrBus <= 0;
			D_T <= 0;
			D_WriteRegEnable <= 0;
			D_RegId <= 0;
			D_MultCalFamily <= 0;
		end
		else begin
			D_PC	<= I_PC;
			D_Instr<=I_MipsInstr;
			D_RsID 	<= Rs_Inter;
			D_RtID 	<= Rt_Inter;
			D_RsData <= RsData_Inter;
			D_RtData <= RtData_Inter;
			D_Shamt	<= Shamt_Inter;
			D_Imm16 <= Imm16_Inter;
			D_InstrBus <= InstrBus_Inter;
			D_T <= T_Inter==4'b0	?	4'b0	:	T_Inter-1;
			D_WriteRegEnable <= WriteRegEnable_Inter;
			D_RegId <= WriteRegId_Inter;
			D_MultCalFamily <= MultCalFamily_Inter;
		end
    end
    
endmodule
